#define CONFIGURE_INIT
#include "system.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <rtems/error.h>
#include <rtems/dosfs.h>
#include <rtems/ide_part_table.h>
#include <rtems/libcsupport.h>
#include <rtems/fsmount.h>
#include <rtems/bdpart.h>
#include <aio.h>
#include <aio_misc.h>
#include <fcntl.h>
#include <strings.h>
#include <sched.h>

#define BUFSIZE 2048

fstab_t fs_table[] = {
  {
    "/dev/hda1","/mnt/hda1","dosfs",
    RTEMS_FILESYSTEM_READ_WRITE,
    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
    0
  },
  {
    "/dev/hda2","/mnt/hda2","dosfs",
    RTEMS_FILESYSTEM_READ_WRITE,
    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
    0
  }
};


void init_part(void)

{
  rtems_status_code rc;

  printf("\n ---> Trying to initialize /dev/hda <---\n");

  rc = rtems_bdpart_register_from_disk("/dev/hda");
  printf("result = %d\n",rc);
}


void mount_part(void)
{
  rtems_status_code rc;

  printf("\n ---> Mount /dev/hda1 and/or /dev/hda2 <--- \n");
  rc = rtems_fsmount( fs_table,
                      sizeof(fs_table)/sizeof(fs_table[0]),
                      NULL);
  printf("result = %d\n",rc);
}

void aio_create_req(void){

  struct aiocb aiocbp;
  ssize_t nbytes; 

  int fd;

  fd = open( "/mnt/hda1/1K", O_RDONLY );
  
  if (fd < 0) printf("error\n");

  memset(&aiocbp,0,sizeof (struct aiocb));
  aiocbp.aio_fildes = fd;
  aiocbp.aio_offset = 0;
  aiocbp.aio_buf = malloc((BUFSIZE / 4 + 1 ) * sizeof(char));
  aiocbp.aio_nbytes = BUFSIZE / 4;

  rtems_aio_enqueue_request(&aiocbp, LIO_READ);
  while ( aio_error( &aiocbp) == EINPROGRESS); 
  
  nbytes = aio_return( &aiocbp);

  printf("we read %d bytes\n",nbytes);
  fflush(stdout);
  close(fd);
  
}
void *menu(void *arg){   


  int result;
  char inbuf[10];
  pthread_t self = pthread_self();
  int policy;
  struct sched_param param;
  
  pthread_getschedparam(self,&policy,&param);

  policy = SCHED_RR;
  param.sched_priority = 30;
  pthread_setschedparam (self,policy,&param);

  for (;;) {
    printf(" =========================\n");
    printf(" RTEMS RTEMS AIO Test Menu \n");
    printf(" =========================\n");
    printf("   i -> initialize chains\n");
    printf("   p -> initialize partition table \n");
    printf("   f -> mount all disks in fs_table\n");
    printf("   a -> add request\n");
    printf("   l -> list request\n");
    printf("   r -> remove request\n");
    printf("   s -> find request by fd\n");
    printf("   S -> find request \n");
    printf("   Enter your selection ==>");
    fflush(stdout);

    inbuf[0] = '\0';
    fgets(inbuf,sizeof(inbuf),stdin);
    switch (inbuf[0]) {
    case 'i':
      rtems_aio_init(NULL);
      break;
    case 'p':
      init_part();
      break;
    case 'f':
      mount_part();
      break;
    case 'a':
      aio_create_req();
      break;
    case 'r':
      rtems_aio_debug();
      break;
    case 'l':
      rtems_aio_debug();
      break;
    case 's':
      printf("Give FD = ");
      fflush(stdout);
      scanf("%d",&result);

      if(rtems_aio_find_fd(result) != NULL)
	printf("Found\n");
      else
	printf("NOT found\n");

      fflush(stdout);
      break;
    case 'S':
      break;
    default:
      printf("Selection `%c` not implemented\n",inbuf[0]);
      fflush(stdout);
      break;
    }

  }
 
  pthread_exit (NULL);

}

void *POSIX_Init (void *argument)
{
  
  pthread_t menu_t;
  int priority, policy, result;
  struct sched_param param;
  pthread_t self = pthread_self();
  
  priority = 3;
  param.sched_priority = priority;
  policy = SCHED_RR;
  pthread_setschedparam (self,policy,&param);

  result = pthread_create (&menu_t, NULL, menu, NULL);
  if (result != 0)
     {
	printf ("Can't create menu thread: %s\n", strerror (errno));
	exit (-1);		
     } 
  
  sleep(1);

  pthread_exit (NULL);
  
}

